from django.shortcuts import render

# Create your views here.


from django.views import View
from utils.user import LoginRequiredJSONMixin
from django.http import JsonResponse
from apps.users.models import Address
from django_redis import get_redis_connection
from apps.goods.models import SKU
class OrderSettlementView(LoginRequiredJSONMixin,View):
    def get(self,request):
        # 1. 必须是登录用户
        user = request.user
        # 2. 获取地址信息
        # 2.1 查询用户 未删除的地址信息
        addresses = Address.objects.filter(user=user,is_deleted=False)
        # 2.2 将查询结果集转换为字典列表
        addresses_list = []
        for address in addresses:
            addresses_list.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'receiver': address.receiver,
                'mobile': address.mobile
            })

        # 3. 获取购物车选中信息
        # 3.1 连接redis
        redis_cli = get_redis_connection('carts')
        # 3.2 获取set
        selected_ids = redis_cli.smembers('selected_%s'%user.id)
        # 3.3 获取hash
        sku_id_counts = redis_cli.hgetall('carts_%s'%user.id)
        # 3.4 查询选中商品的信息
        new_dict = {}
        for id in selected_ids:
            new_dict[int(id)] = int(sku_id_counts[id])
        # 3.5 将对象转换为字典
        skus_list = []
        for sku_id,count in new_dict.items():
            sku = SKU.objects.get(id=sku_id)
            skus_list.append({
                'id':sku.id,
                'name': sku.name,
                'price': sku.price,
                'count': count,
                'default_image_url': sku.default_image.url
            })

        # 4. 运费
        freight = 10
        # 5. 返回响应
        context = {
            'addresses':addresses_list,
            'skus':skus_list,
            'freight':freight

        }

        return JsonResponse({'code':0,'errmsg':'ok','context':context})

import json
from apps.orders.models import OrderInfo,OrderGoods
class OrderCommitView(View):
    def post(self,request):
        # 必须是登录用户
        user = request.user
        # ①. 接收数据
        data = json.loads(request.body.decode())
        # ②. 提取数据
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')
        # ③. 验证参数
        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return JsonResponse({'code':400,'errmsg':'没有此地址'})
        if pay_method not in [1,2]:
            return JsonResponse({'code':400,'errmsg':'支付方式错误'})

        # ④. 数据入库
            # 1. 保存订单信息
            # 1.1 通过年月日时分秒生成订单id
        from datetime import datetime
        from django.utils import timezone
        order_id = timezone.now().strftime('%Y%m%d%H%M%S%f') + '%09d' % user.id
            # 1.2 总数量和总金额 先记为0
        total_count = 0
        from decimal import Decimal
        total_amount = Decimal('0')
            # 1.3 运费
        freight = Decimal('10')
            # 1.4 订单状态 -- 由支付方式决定
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        from django.db import transaction

        with transaction.atomic():
            # 事物开始点
            start_point = transaction.savepoint()

            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count=total_count,
                total_amount=total_amount,
                freight=freight,
                pay_method=pay_method,
                status=status
            )

                # 2. 保存订单商品信息
            redis_cli = get_redis_connection('carts')
                # 2.1 获取redis中的数据 hash
            sku_id_counts = redis_cli.hgetall('carts_%s'%user.id)
                # set
            selected_ids = redis_cli.smembers('selected_%s'%user.id)
                # 2.2 把数据整理一下 选中的字典
            new_selected_carts = {}
            for id in selected_ids:
                new_selected_carts[int(id)] = int(sku_id_counts[id])
                # 2.3 遍历
            for sku_id,cart_count in new_selected_carts.items():
                while True:
                    # 2.4 根据商品id查询商品信息
                    sku = SKU.objects.get(id=sku_id)
                    # 2.5 判断商品库存 如果库存不足 下单失败
                    if cart_count > sku.stock:
                        # 事务的回滚
                        transaction.savepoint_rollback(start_point)
                        return JsonResponse({'code':400,'errmsg':'库存不足'})
                    # 2.6 如果库存充足 应该让sku的销量增加,库存减少
                    # sku.stock -= cart_count
                    # sku.sales += cart_count
                    # sku.save()

                    # 模拟延迟
                    # from time import sleep
                    # sleep(7)
                    # 使用乐观锁并发下单
                    # 记录当前值
                    old_stock = sku.stock
                    new_stock = sku.stock - cart_count
                    new_sales = sku.sales + cart_count
                    # 更新前 判断记录的值 是否和现在的值一致
                    result = SKU.objects.filter(id=sku_id,stock=old_stock).update(stock=new_stock,sales=new_sales)
                    if result == 0:
                        transaction.savepoint_rollback(start_point)
                        return JsonResponse({'code':400,'errmsg':'库存不足下单失败'})
                    # 2.7 统计总数量和总金额
                    order.total_count += cart_count
                    order.total_amount += (cart_count*sku.price)
                    # 2.8 保存订单商品信息
                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=cart_count,
                        price=sku.price
                    )
                    # 下单成功或者失败就跳出循环
                    break
                # 3. 修改总数量和总金额
            order.save()
            #　事物提交
            transaction.savepoint_commit(start_point)

            # 4. 把购物车中 选中的信息删除

        redis_cli.hdel('carts_%s'%user.id,*selected_ids)
        redis_cli.srem('selected_%s'%user.id,*selected_ids)
        # ⑤. 返回响应
        return JsonResponse({'code':0,'errmsg':'ok','order_id':order_id})